package com.jdk.demo.mappedByteBuffer;

import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

// MappedByteBuffer map(FileChannel.MapMode mode, long position, long size)方法的作用是将此通道的文件区域直接映射到内存中
// 只读：试图修改得到的缓冲区将导致抛出ReadOnlyBufferException异常
// 读取/写入：对得到的缓冲区的更改最终将传播到文件，该更改对映射到同一文件的其他程序不一定是可见的
// 专用：对得到的缓冲区的更改不会传播到文件，并且该更改对映射到同一文件的其他程序也是不可见的；相反，会创建缓冲区已修改部分的专用副本
// 此方法返回的映射字节缓冲区position为0，limit和capacity为size；其mark是不确定的。在缓冲区本身被作为垃圾回收之前，该缓冲区及其表示的映射关系都是有效的
// 映射关闭一经创建，就不再依赖于创建它时所用的文件通道。特别是关闭该通道对映射关系的有效性没有任何影响。
// mode：根据只读、读取/写入、专用来映射文件
// position：文件中的位置，映射区域从此位置开始，必须为非负数
// size：要映射的区域大小，必须为非负数且不大于Integer.MAX_SIZE
public class MappedDemo {

	private static final int MAP_SIZE = 1024 * 5; // 5K

	public static void main(String args[]){
        try {
        	RandomAccessFile f = new RandomAccessFile("E:/zsl/temp2.txt", "r");
            RandomAccessFile world = new RandomAccessFile("E:/zsl/temp3.txt", "rw");
            FileChannel fc = f.getChannel();
            FileChannel worldChannel = world.getChannel();

            int position = 0;
            long length = fc.size();

            while(position < length){
            	long remaining = length - position;
            	int bytestomap = (int)Math.min(MAP_SIZE, remaining);
            	MappedByteBuffer buf = fc.map(FileChannel.MapMode.READ_ONLY, position, bytestomap);
            	MappedByteBuffer worldBuf = worldChannel.map(FileChannel.MapMode.READ_WRITE, position, bytestomap);

            	byte[] bytes = new byte[worldBuf.limit()];
            	buf.get(bytes);
            	System.out.println(new String(bytes, "utf-8"));

            	buf.flip();
            	position += worldBuf.limit();
            	worldBuf.put(buf);
            }

            fc.close();
            f.close();
            world.close();
            worldChannel.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
